
/** 
 * @file		Ethernet.c
 * @brief				
 * @details	Project	: BHS-Ethernet 
 * 
 * 
 * @author	Seven Zeng
 * @date		15/12/2019
 * @copyright	MICC Tech All rights reserved
 * 
 ************************************************************** 
 * @par
 * 
 * 
 ************************************************************** 
 */
 
 
//===============================INCLUDE==========================

#define ETHERNET_DEF
#include "Ethernet.h"

#include "HAL.h"
#include "main.h"
#include "cmsis_os.h"
//================================================================





//=========================TYPE DEFINITIONS=======================


//================================================================




//=========================CONST DEFINITIONS======================
#define ETH_RX_START		0X0000
#define ETH_RX_END			0X0FFF
#define ETH_TX_START		0X1000
#define ETH_TX_END			0X1FFF


//================================================================




//=========================VARIABLE DECLARATIONS==================




//================================================================




//=========================ROUTINE PROTOTYPES=====================

/**
 * 
 */
void EtherNet_Init(void) 
{

	LL_GPIO_ResetOutputPin (ETH_NRST_GPIO_Port, ETH_NRST_Pin);
	osDelay (1);	
	LL_GPIO_SetOutputPin (ETH_NRST_GPIO_Port, ETH_NRST_Pin);
	osDelay (1);	

	//  T_SPI_INFO ethernetSPI;
	//  SPI_Init (&ethernetSPI, SPI1, 500000, 0);
	ENC28J60_Init ();

	ENC28J60_Reset ();

	// as per errata requested
	osDelay (1);

	ENC28J60_SetBank(0x00);

	// Wait for clock ready
	while ((ENC28J60_ReadEthControlRegister (BANK0_ESTAT) & 0x01) == 0);

	// As per errata requested, use the front 4k buffer as rx buffer
	ENC28J60_WriteControlRegister (BANK0_ERXSTH, ETH_RX_START >> 8);
	ENC28J60_WriteControlRegister (BANK0_ERXSTL, ETH_RX_START & 0XFF);
	ENC28J60_WriteControlRegister (BANK0_ERXNDH, ETH_RX_END >> 8);
	ENC28J60_WriteControlRegister (BANK0_ERXNDL, ETH_RX_END & 0XFF);

	// all others are tx buffer
	ENC28J60_WriteControlRegister (BANK0_ETXSTH, ETH_TX_START >> 8);
	ENC28J60_WriteControlRegister (BANK0_ETXSTL, ETH_TX_START & 0XFF);
	ENC28J60_WriteControlRegister (BANK0_ETXNDH, ETH_TX_END >> 8);
	ENC28J60_WriteControlRegister (BANK0_ETXNDL, ETH_TX_END & 0XFF);

	ENC28J60_SetBank(0x01);
	// Set all filter bit
	//ENC28J60_SetEthBits (BANK1_ERXFCON, 0xBF);
	// Or all bits rather than and
	//ENC28J60_ResetEthBits (BANK1_ERXFCON, 0xBF);

	// Disable all filters except crc invalid
	ENC28J60_WriteControlRegister (BANK1_ERXFCON, 0x20);

	ENC28J60_SetBank(0x02);
	// Enable TxPause, RxPause, RxEn, Disable Passall
	ENC28J60_WriteControlRegister(BANK2_MACON1, 0x0D);

	// PADCFG:101, TxCRCEN:1, PHDREB:0, HFRMEN:0, FRMLNEV:1, FULDPX:0
	ENC28J60_WriteControlRegister(BANK2_MACON3, 0xB2);

	// DEFER:1, BPEN:0, NOBKOFF:0
	ENC28J60_WriteControlRegister(BANK2_MACON4, 0x40);

	// Max frame length 1518(0x05EE)
	ENC28J60_WriteControlRegister(BANK2_MAMXFLL, 0xEE);
	ENC28J60_WriteControlRegister(BANK2_MAMXFLH, 0x05);

	// back-to-back inter-packet gap
	ENC28J60_WriteControlRegister(BANK2_MABBIPG, 0X15);

	// non back-to-back inter-packet gap
	ENC28J60_WriteControlRegister(BANK2_MAIPGL, 0X12);
	ENC28J60_WriteControlRegister(BANK2_MAIPGL, 0X0C);

	ENC28J60_SetBank(0x03);
	// Program mac as B8-AE-ED-B3-C1-34
	ENC28J60_WriteControlRegister(BANK3_MAADR1, 0X34);
	ENC28J60_WriteControlRegister(BANK3_MAADR1, 0XC1);  
	ENC28J60_WriteControlRegister(BANK3_MAADR1, 0XB3);  
	ENC28J60_WriteControlRegister(BANK3_MAADR1, 0XED);  
	ENC28J60_WriteControlRegister(BANK3_MAADR1, 0XAE);
	ENC28J60_WriteControlRegister(BANK3_MAADR1, 0XB8);

	// Set phy to half duplex
	ENC28J60_WritePHYRegister(PHCON1, 0X0000);
	// Disable loop back
	ENC28J60_WritePHYRegister(PHCON2, 0X0100);
	// Config LED
	ENC28J60_WritePHYRegister(PHLCON, 0X3212);
	// enable auto inc
	ENC28J60_SetEthBits (BANK3_ECON2, 0x80);
	// Enable eth rx
	ENC28J60_SetEthBits (BANK3_ECON1, 0x04);

	// the first 2 bytes are used next packet pointer of packet header
	ethRxBuffer.header.bits.nextPackPointerLo = ETH_RX_START & 0xFF;
	ethRxBuffer.header.bits.nextPackPointerHi = ETH_RX_START >> 8;

}

/**
 * 
 */
void EtherNet_ReadPackage()
{
	u16 byteCount;

	// Set read pointer
	ENC28J60_SetBank (0);
	ENC28J60_WriteControlRegister (BANK0_ERDPTL, ethRxBuffer.header.bits.nextPackPointerLo);
	ENC28J60_WriteControlRegister (BANK0_ERDPTH, ethRxBuffer.header.bits.nextPackPointerHi);

	// Continously read header
	ENC28J60_ReadBuffer(ethRxBuffer.header.bytes, sizeof(ethRxBuffer.header.bytes));

	byteCount = ethRxBuffer.header.bits.byteCountLo + ((u16)ethRxBuffer.header.bits.byteCountHi << 8);

	if (byteCount > sizeof(ethRxBuffer.data)) {

		byteCount = sizeof(ethRxBuffer.data);
	}

	// continously read data
	ENC28J60_ReadBuffer (ethRxBuffer.data, byteCount);

	// Decrement the packge count
	ENC28J60_SetEthBits (BANK0_ECON2, 0x40);

}

static volatile u8 readRequest = 0;
static volatile u8 readValue = 0;
static volatile u8 readAddr = 0;
static volatile u8 readBank = 0;

static volatile u8 writeValue = 0;
static volatile u8 writeRequest = 0;
static volatile u8 writeAddr = 0;
static volatile u8 writeBank = 0;

static volatile u8 readEth = 1;
/**
 * 
 */
void EtherNet_ManualAccess(void)
{
    if (readRequest) {
	  ENC28J60_SetBank (readBank);
      readRequest = 0;
	  if (readEth) {
	  	readValue = ENC28J60_ReadEthControlRegister (readAddr);
	  } else {
		readValue = ENC28J60_ReadMACOrMIIControlRegister (readAddr);
	  }
    }


	if (writeRequest) {
	  writeRequest = 0;
	  ENC28J60_SetBank (writeBank);
	  ENC28J60_WriteControlRegister (writeAddr, writeValue);
	}

}

/**
 * @return
 */
u8 EtherNet_GetPackageCount(void)
{
	ENC28J60_SetBank (1);
	return ENC28J60_ReadEthControlRegister (BANK1_EPKTCNT);

}


//================================================================




